package com.gistmap.sideline.service;

import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.gistmap.sideline.dto.LoginDTO;
import com.gistmap.sideline.dto.RegistDTO;
import com.gistmap.sideline.dto.UserAdditionDTO;
import com.gistmap.sideline.dto.UserCache;
import com.gistmap.sideline.entity.User;
import com.gistmap.sideline.exception.ServiceException;
import com.gistmap.sideline.mapper.UserMapper;
import com.gistmap.sideline.util.PasswordUtil;
import com.github.afkbrb.avatar.Avatar;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.util.UUID;

@Service
public class UserService{

    @Value("${sideline.avatar.savePath}")
    private String savePath;

    @Autowired
    private UserMapper userMapper;
    @Autowired
    private MailService mailService;
    @Autowired
    private RedisService redisService;
    @Autowired
    private PasswordUtil passwordUtil;

    public String login(LoginDTO dto){
        if (StrUtil.isAllBlank(dto.getEmail(), dto.getUsername())) {
            throw new ServiceException(1001, "账号或邮箱为空");
        }
        User user = userMapper.findByUsernameOrEmail(dto.getUsername(), dto.getEmail());
        if (user == null) {
            throw new ServiceException(1002, "账号或邮箱不存在");
        }
        String password = passwordUtil.translate(dto.getPassword());
        if (!user.getPassword().equals(password)) {
            throw new ServiceException(1003, "密码错误");
        }
        return setToken(new UserCache(user));
    }

    public String register(RegistDTO dto){
        if (!validEmail(dto.getEmail())) {
            throw new ServiceException(1004, "邮箱已被注册");
        }
        if (!validUsername(dto.getUsername())) {
            throw new ServiceException(1005, "用户名已被注册");
        }
        User user = new User();
        user.setEmail(dto.getEmail());
        user.setUsername(dto.getUsername());
        user.setPassword(passwordUtil.translate(dto.getPassword()));
        String avaLoc = generateAvatar(StrUtil.sub(dto.getEmail(), 0 ,5));
        user.setAvatar(avaLoc);
        userMapper.insert(user);
        String token = setToken(new UserCache(user));
        sendActiveEmail(token, user.getEmail(), user.getUsername());
        return token;
    }


    /**
     *  激活账号
     * @param code       随机码
     * @param token      token
     * @return
     */
    @Async
    public void active(String code, String token){
        Object isExist = redisService.get(code);
        // random会设的久一点，这里防止多次点击激活url
        // 但还是会有在有效期不点激活链接的情况,在个人主页加个按钮补发(当且距离第一次登陆超过1天且isActive为false的情况)
        if (isExist == null) {
            throw new ServiceException(1006, "你已激活本账号");
        }
        UserCache currentUser = (UserCache) redisService.get(token);
        User user = userMapper.selectById(currentUser.getId());
        user.setActive(true);
        userMapper.updateById(user);
        // 移除随机码
        redisService.del(code);
        // 更新user
        redisService.set(token, new UserCache(user), 130);
    }


    /**
     * 发送激活邮件
     * @param token
     */
    @Async
    public void sendActiveEmail(String token, String to, String name){
        // todo 生产随机码
        String code = RandomUtil.randomString(12);
        redisService.set(code, 1, 24*60);
        // todo 拼接url
        StringBuffer sb = new StringBuffer();
        sb.append("http://www.xxx.com/").append("前端路由地址")
                .append("/").append(code).append("-").append(token);
        // todo 放到模板里发送
        mailService.sendActiveMail(to, name, sb.toString());
    }

    public boolean validEmail(String email) {
        return userMapper.selectOne(new QueryWrapper<User>()
                .lambda()
                .eq(User::getEmail, email)) == null;
    }

    public boolean validUsername(String username) {
        return userMapper.selectOne(new QueryWrapper<User>()
                .lambda()
                .eq(User::getUsername, username)) == null;
    }

    private String setToken(UserCache user) {
        String uuidToken= UUID.randomUUID().toString().replace("-","");
        int time = RandomUtil.randomInt(6, 8);
        redisService.set(uuidToken, user, time);
        return uuidToken;
    }

    private String generateAvatar(String name){
        Avatar avatar = new Avatar();
        String randomStr = RandomUtil.randomString(7);
        String loc = savePath + name + randomStr;
        avatar.saveAsPNG(loc);
        return loc;
    }

    public void addition(UserAdditionDTO dto) {
        User user = userMapper.selectById(dto.getId());
        user.setName(dto.getName());
        user.setDescription(dto.getDescription());
        user.setProfession(dto.getProfession());
        user.setSex(dto.getSex());
        userMapper.updateById(user);
    }
}
